﻿function Install-SharePointPrereqs
{
    <# 
     .Synopsis
        Launches the SharePoint Prerequisite Installer. Optionally launches the prerequisite installer with local installation files.

     .Description
        This script launches the SharePoint Prerequisite Installer in 1 of 2 modes. If the script is executed with no switches, the prerequisite installer will connect to the Internet and download the installation files needed. If the -UseLocalFiles switch is selected, then this script will create an unattended installation answer file that points to local copies of the installation software and then copy it to the SharePoint Prerequisite Installer directory.

     .Parameter UseLocalFiles
        Use this switch to indicate that the prerequisite installer should use local copies of the install software instead of connecting to the Internet and downloading.

     .Parameter PathToSpPrereqFiles
        The full file system path where the installation source files for the SharePoint Prerequisites are located. 
        The default value for this parameter is 'C:\ProgramData\SharePoint Total Automation Toolkit\Software\01-PrerequisiteInstallerFiles'

     .Parameter PathToSpInstallFiles
        The full file system path where the installation source files for SharePoint are located. 
        The default value for this parameter is 'C:\ProgramData\SharePoint Total Automation Toolkit\Software\04-SharePointServer2013'      

     .Parameter Restart
        Use this switch to automatically restart the server at the end of this script.

     .Parameter SharePointVersion
        Use this parameter to indicate which SharePoint Version to install. Valid choices are '2010' and '2013'

     .Example
        Install-SharePointPrereqs -SharePointVersion 2013

     .Example
        Install-SharePointPrereqs -SharePointVersion 2013 -PathToSpPrereqFiles 'C:\ProgramData\SharePoint Total Automation Toolkit\Software\01-PrerequisiteInstallerFiles' -PathToSpInstallFiles 'C:\ProgramData\SharePoint Total Automation Toolkit\Software\04-SharePointServer2013'
        
        # If using a custom location for the installation files default configuration file path and structure, provide discrete paramaters to each subdirectory

    #>
    [CmdletBinding(DefaultParametersetName="OnlineInstall")]
    param([parameter(ParameterSetName = "LocalInstall", 
                     Mandatory = $false,
                     HelpMessage = "Use this switch to indicate that the prerequisite installer should use local copies of the install software instead of connecting to the Internet and downloading.")]
                     [switch]$UseLocalFiles,
          [parameter(ParameterSetName = "LocalInstall", 
                     Mandatory = $false,
                     HelpMessage = "The full file system path where the installation source files for the SharePoint Prerequisites are located. The default value for this parameter is 'C:\ProgramData\SharePoint Total Automation Toolkit\Software\01-PrerequisiteInstallerFiles'")]
                     [string]$PathToSpPrereqFiles = ($env:ProgramData + "\SharePoint Total Automation Toolkit\Software\01-PrerequisiteInstallerFiles"),
	      [parameter(ParameterSetName = "LocalInstall", 
                     Mandatory = $false,
                     HelpMessage = "The full file system path where the installation source files for SharePoint are located. The default value for this parameter is 'C:\ProgramData\SharePoint Total Automation Toolkit\Software\04-SharePointServer2013'")]
                     [string]$PathToSpInstallFiles = ($env:ProgramData + "\SharePoint Total Automation Toolkit\Software\04-SharePointServer2013"),
          [parameter(ParameterSetName = "LocalInstall",
                     Mandatory = $true,
                     HelpMessage = "Use this parameter to indicate which SharePoint Version to install. Valid choices are '2010' and '2013'")]
                     [ValidateSet ("2010","2013")]
          [parameter(ParameterSetName = "OnlineInstall",
                     Mandatory = $true,
                     HelpMessage = "Use this parameter to indicate which SharePoint Version to install. Valid choices are '2010' and '2013'")]
                     [ValidateSet ("2010","2013")]
                     [string]$SharePointVersion,
          [parameter(ParameterSetName = "LocalInstall",
                     Mandatory = $false,
                     HelpMessage = "Use this switch to automatically reboot at the end of this script.")]
          [parameter(ParameterSetName = "OnlineInstall",
                     Mandatory = $false,
                     HelpMessage = "Use this switch to automatically reboot at the end of this script.")]
                     [switch]$Restart = $false)

    # First determine which OS we are installing on
    $osVersionMajor = [System.Environment]::OSVersion.Version.Major
    $osVersionMinor = [System.Environment]::OSVersion.Version.Minor

	$rebootStatus = Get-PendingReboot
	if ($rebootStatus.RebootPending -eq $true)
	{
		Write-Host "NOTE: A system restart is required. Please restart the system prior to continuing with the SharePoint prerequisite installation." -ForegroundColor Yellow
		Write-Host "      When the system restarts please rerun this script until you no longer receive a restart request." -ForegroundColor Yellow
		throw 
	}

    # Clean up any old prerequisite installer argument files prior to continuing
    $argumentsFile = ($PathToSpInstallFiles + "\PrerequisiteInstaller.Arguments.txt")
    Remove-Item $argumentsFile -Force -Confirm:$false -ErrorAction SilentlyContinue    

    switch ($PSCmdlet.ParameterSetName)
    {
        "LocalInstall"
        {
            $installType = "Offline installation using local files"

            switch ($SharePointVersion)
            {
                '2010'
                {                    
                    # Build up the arguments list for the Prerequisite Installer
                    $preReqArgs = ''

                    throw "Offline installation for SP2010 not yet implemented. Use online mode instead."
                }
                '2013'
                {
                    # Build up the arguments list for the Prerequisite Installer
                    $preReqArgs = '/unattended /NETFX:"' + $PathToSpPrereqFiles + '\dotnetfx45_full_x86_x64.exe" /PowerShell:"' + $PathToSpPrereqFiles + '\Windows6.1-KB2506143-x64.msu" /SQLNCli:"' + $PathToSpPrereqFiles + '\sqlncli.msi" /IDFX:"' + $PathToSpPrereqFiles + '\Windows6.1-KB974405-x64.msu" /Sync:"' + $PathToSpPrereqFiles + '\Synchronization.msi" /AppFabric:"' + $PathToSpPrereqFiles + '\WindowsServerAppFabricSetup_x64.exe" /IDFX11:"' + $PathToSpPrereqFiles + '\MicrosoftIdentityExtensions-64.msi" /MSIPCClient:"' + $PathToSpPrereqFiles + '\setup_msipc_x64.msi" /WCFDataServices:"' + $PathToSpPrereqFiles + '\WcfDataServices.exe" /KB2671763:"' + $PathToSpPrereqFiles + '\AppFabric1.1-RTM-KB2671763-x64-ENU.exe" /WCFDataServices56:"' + $PathToSpPrereqFiles + '\WcfDataServices56.exe"'
                }
            }

            # Write the arguments list to arguments text file (having already removed any old versions first if they exist)
            # NOTE: This approach is used instead of just passing the arguments on the command line in order to avoid an error with long argument strings
            # ALSO NOTE: We use the .NET AppendAllText function in order to avoid adding a line break at the end of the file...the prerequisite installer 
            #            is VERY picky about the format of the file
            [System.IO.File]::AppendAllText($argumentsFile, $preReqArgs, [System.Text.Encoding]::ASCII)
        }    
        default
        {
            $installType = "Online installation using file download"
        }    
    }

    # Initialize Progress Variables
    [int]$progressNumPhases = 1
    [int]$progressNumPhasesComplete = 0
    [int]$progressNumTasksComplete = 0
    [int]$progressTotalTasks = 0
    [int]$progressTotal = 0
    [int]$progressBarId = 100
    $startTime = [System.DateTime]::Now


    Write-Host "Beginning the SharePoint Prerequisites installation."

	[int]$progressTotalTasks = 1

	#region Installation using the SharePoint Prerequisite Installer

	# Launch the SharePoint Prerequisite Installer
	$setupExe = ($PathToSpInstallFiles + "\PrerequisiteInstaller.exe")
	$preReqProcessStartInfo = New-Object System.Diagnostics.ProcessStartInfo
	$preReqProcessStartInfo.FileName = $setupExe
	$preReqProcessStartInfo.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Minimized
	$setupExeInstance = [System.Diagnostics.Process]::Start($preReqProcessStartInfo)
	$step = 5
	$value = 0

	while (-not ($setupExeInstance.HasExited)){
		$currentRuntime = [System.DateTime]::Now - $startTime
		Write-Progress -Id $progressBarId -Activity "Installing SharePoint Prerequisites" -PercentComplete ($value+=$step) -CurrentOperation $installType -Status ("The current operation has been running for {0}:{1}:{2}" -f $currentRuntime.Hours.ToString("00"), $currentRuntime.Minutes.ToString("00"), $currentRuntime.Seconds.ToString("00"))
     
		if ($value -ge 100) { $value = 0}

		Start-Sleep -Seconds 1
	}

    switch ($setupExeInstance.ExitCode)
    {
        0
        {
		    Write-Host "     SharePoint Prerequisites Successfully Installed"
        }

        1
        {
		    Write-Error "     Another instance of the SharePoint Prerequisite installer is already running."
		    throw
        }

        2
        {
		    Write-Error "     Invalid command line parameters were passed to the SharePoint Prerequisite Installer.  Please check the file $argumentsFile"
		    throw
        }

        1001
        {
		    if ($Restart -eq $true)
		    {
			    Restart-Computer
		    }
		    else
		    {
			    Write-Host "NOTE: A system restart was already pending from another installation. Please restart the system prior to continuing with the SharePoint installation." -ForegroundColor Yellow
			    Write-Host "      When the system restarts please rerun this script until you no longer receive a restart request." -ForegroundColor Yellow
		    }
        }

        3010
        {
		    if ($Restart -eq $true)
		    {
			    Restart-Computer
		    }
		    else
		    {
			    Write-Host "NOTE: A system restart is required. Please restart the system prior to continuing with the SharePoint installation." -ForegroundColor Yellow
			    Write-Host "      When the system restarts please rerun this script until you no longer receive a restart request." -ForegroundColor Yellow
		    }
        }

        default
        {
		    $exitCode = $setupExeInstance.ExitCode
		    Write-Error "     Installation of SharePoint Prerequisites Failed with exit code ($exitCode)"
		    throw
        }
    }

	#endregion

    # Increment the Phase Completion Counter
    $progressNumPhasesComplete++

    Write-Progress -Id $progressBarId -Activity "Installing SharePoint Prerequisites" -Status "Finishing" -PercentComplete 100 -CurrentOperation "" -Completed

    Write-Host "SharePoint Prerequisites installation complete."
    
}